/*
 *  Copyright 2008-2010 www.jrails.org
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.rails.core.web;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

@SuppressWarnings("serial")
public final class ControllerServlet extends HttpServlet {

	private ServletConfig config;

	protected final Logger logger = Logger.getLogger(ControllerServlet.class);

	public ControllerServlet() {
		super();
	}
	
	@Override
	public void init(ServletConfig config) throws ServletException {    
	    super.init(config);    
	    this.config = config;    
	}  

	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response) {
		try {
			final Action action = new Action(config,request, response);
			logger.debug("Request Path : " + request.getServletPath());
			logger.debug("Request method : " + request.getMethod());
			execute(action,action.getController());
		} catch (PathException e) {
			logger.error(e.getMessage(), e);
			sendError(response, 500);
		} catch (ClassNotFoundException e) {
			logger.error("访问的控制器不存在!",e);
			sendError(response, 500);
		}
	}

	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response) {
		doGet(request, response);
	}

	@SuppressWarnings("unchecked")
	private void execute(final Action action,final Class<? extends ControllerBase> c) {
		ControllerBase contro = null;
		try {
			final Constructor<ControllerBase> constructor = 
				(Constructor<ControllerBase>) c.getConstructor(Action.class);
			contro = constructor.newInstance(action);
			logger.debug("Controller : " + contro.getClass().getName());
			logger.debug("Action : " + action.getActionName());
			logger.debug("Params : " + contro.params);
			if (action.isActive()) {
				Method mtd = c.getDeclaredMethod(action.getActionName());
				mtd.invoke(contro);
			}
		}catch (Exception e) {
			if (e instanceof NoSuchMethodException && contro instanceof ControllerBase) {
				execute(action,(Class<? extends ControllerBase>)c.getSuperclass());
			} else {
				if(e instanceof InstantiationException)
					logger.error(action.getActionName() + "  不存在或者内部错误!",e);
				else
					logger.error(e.getMessage(), e);
				
				sendError(action.getResponse(),500);
			}
		}

	}

	private void sendError(HttpServletResponse response, int error) {
		try {
			response.sendError(error);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
	}

}
